// excerpts from http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)

#define __STDC_LIMIT_MACROS
#include "TimerQueue.h"

#include "logging/Logging.h"
#include "EventLoop.h"
#include "Timer.h"
#include "TimerId.h"

#include <boost/bind.hpp>

#include <sys/timerfd.h>

namespace learnmuduo
{
namespace detail
{

int createTimerfd()  // 创建timerfd的工具函数
{
  int timerfd = ::timerfd_create(CLOCK_MONOTONIC, // 使用单调时钟，设置非阻塞和CLOEXEC
                                 TFD_NONBLOCK | TFD_CLOEXEC);
  if (timerfd < 0)
  {
    LOG_SYSFATAL << "Failed in timerfd_create";
  }
  return timerfd;
}

struct timespec howMuchTimeFromNow(muduo::Timestamp when) // 计算现在到目标时间的间隔
{
  int64_t microseconds = when.microSecondsSinceEpoch()
                         - muduo::Timestamp::now().microSecondsSinceEpoch(); // 微秒差值
  if (microseconds < 100)
  {
    microseconds = 100; // 至少延迟100微秒，避免立即触发
  }
  struct timespec ts;
  ts.tv_sec = static_cast<time_t>(
      microseconds / muduo::Timestamp::kMicroSecondsPerSecond);
  ts.tv_nsec = static_cast<long>(
      (microseconds % muduo::Timestamp::kMicroSecondsPerSecond) * 1000);
  return ts;
}

void readTimerfd(int timerfd, muduo::Timestamp now) // 读取timerfd清除可读事件
{
  uint64_t howmany;
  ssize_t n = ::read(timerfd, &howmany, sizeof howmany); // 读取触发次数
  LOG_TRACE << "TimerQueue::handleRead() " << howmany << " at " << now.toString();
  if (n != sizeof howmany)
  {
    LOG_ERROR << "TimerQueue::handleRead() reads " << n << " bytes instead of 8";
  }
}

void resetTimerfd(int timerfd, muduo::Timestamp expiration) // 重新设置timerfd下一次触发时间
{
  // wake up loop by timerfd_settime()
  struct itimerspec newValue;
  struct itimerspec oldValue;
  bzero(&newValue, sizeof newValue);
  bzero(&oldValue, sizeof oldValue);
  newValue.it_value = howMuchTimeFromNow(expiration); // 启动定时器
  int ret = ::timerfd_settime(timerfd, 0, &newValue, &oldValue);
  if (ret)
  {
    LOG_SYSERR << "timerfd_settime()";
  }
}

}
} // namespace learnmuduo

using namespace learnmuduo;
using namespace learnmuduo::detail;

TimerQueue::TimerQueue(EventLoop* loop)
  : loop_(loop),
    timerfd_(createTimerfd()),
    timerfdChannel_(loop, timerfd_),
    timers_()
{
  timerfdChannel_.setReadCallback(
      boost::bind(&TimerQueue::handleRead, this)); // 把timerfd可读事件绑定到handleRead
  // we are always reading the timerfd, we disarm it with timerfd_settime.
  timerfdChannel_.enableReading(); // 立即关注可读事件
}

TimerQueue::~TimerQueue()
{
  ::close(timerfd_);
  // do not remove channel, since we're in EventLoop::dtor();
  for (TimerList::iterator it = timers_.begin();
      it != timers_.end(); ++it)
  {
    delete it->second;
  }
}

TimerId TimerQueue::addTimer(const TimerCallback& cb,
                             muduo::Timestamp when,
                             double interval)
{
  Timer* timer = new Timer(cb, when, interval);
  loop_->assertInLoopThread(); // 确保在事件循环线程调用
  bool earliestChanged = insert(timer);  // 插入集合并判断是否刷新最早时间

  if (earliestChanged)
  {
    resetTimerfd(timerfd_, timer->expiration());  // 若是最早到期，重设timerfd
  }
  return TimerId(timer);
}

void TimerQueue::handleRead()
{
  loop_->assertInLoopThread();
  muduo::Timestamp now(muduo::Timestamp::now());
  readTimerfd(timerfd_, now); // 读timerfd清除溢出

  std::vector<Entry> expired = getExpired(now); // 取出所有到期定时器

  // safe to callback outside critical section
  for (std::vector<Entry>::iterator it = expired.begin();
      it != expired.end(); ++it)
  {
    it->second->run(); // 执行定时器回调
  }

  reset(expired, now); // 处理重复定时器并重新安排
}

std::vector<TimerQueue::Entry> TimerQueue::getExpired(muduo::Timestamp now)
{
  std::vector<Entry> expired; // 存放到期定时器
  Entry sentry = std::make_pair(now, reinterpret_cast<Timer*>(UINTPTR_MAX)); // 构造哨兵，确保lower_bound找到第一个未到期元素
  TimerList::iterator it = timers_.lower_bound(sentry); // lower_bound: 用来在保持排序的前提下找到“第一个不小于（≥）给定值”的元素位置
  assert(it == timers_.end() || now < it->first); // sentry 让 `set::lower_bound()` 返回的是第一个未到期的 Timer 的迭代器, 因此断言中是 ` < ` 而非 ` <= `
  std::copy(timers_.begin(), it, back_inserter(expired)); // 将到期部分拷贝出来; back_inserter: 据你传入的容器，构造一个“输出迭代器”，把所有写入操作（例如 *it = value 或 it++）转化为向容器调用 push_back(value)
  timers_.erase(timers_.begin(), it); // 从集合中删除这些到期定时器

  return expired; // 返回到期定时器列表
}

void TimerQueue::reset(const std::vector<Entry>& expired, muduo::Timestamp now)
{
  muduo::Timestamp nextExpire; // 记录下一次触发时间

  for (std::vector<Entry>::const_iterator it = expired.begin();
      it != expired.end(); ++it)
  {
    if (it->second->repeat())
    {
      it->second->restart(now); // 重复定时器重新计算到期时间
      insert(it->second);
    }
    else
    {
      // FIXME move to a free list
      delete it->second;
    }
  }

  if (!timers_.empty())
  {
    nextExpire = timers_.begin()->second->expiration();
  }

  if (nextExpire.valid())
  {
    resetTimerfd(timerfd_, nextExpire); // 重设timerfd以触发下一次
  }
}

bool TimerQueue::insert(Timer* timer)
{
  bool earliestChanged = false; // 标记最早到期是否被更新
  muduo::Timestamp when = timer->expiration(); // 获取定时器到期时间
  TimerList::iterator it = timers_.begin();
  if (it == timers_.end() || when < it->first)
  {
    earliestChanged = true; // 如果队列为空或比当前最早时间更早
  }
  std::pair<TimerList::iterator, bool> result =
          timers_.insert(std::make_pair(when, timer)); // 插入定时器
  assert(result.second); // 确保插入成功
  return earliestChanged; // 返回最早时间是否改变
}
